import React, { Component } from "react";
import * as d3 from "d3";
export default class MiniChart extends Component {
  constructor(props) {
    super(props);
    this.myRef = React.createRef();
    this.state = {
      nodes: this.props.nodes,
      links: this.props.links,
    };
  }
  componentDidMount = () => {
    console.log(this.state, "MiniChart中接收到的参数");
    if (this.state.nodes !== undefined) {
      this.drawChart();
    }
  };
  componentDidUpdate = () => {
    if (this.state.nodes !== undefined) {
      this.drawChart();
    }
  };
  drawChart() {
    const data = {
      nodes: this.state.nodes,
      links: this.state.links,
    };
    var zoom = d3
      .zoom()
      .scaleExtent([0.1, 4]) // 设置缩放的范围
      .on("zoom", zoomed); // 定义缩放事件的处理函数
    const svg = d3.select(this.myRef.current);
    svg.call(zoom);
    const width = +svg.attr("width");
    const height = +svg.attr("height");

    // tooltip for mouseover functionality
    var tooltip = d3
      .select("body")
      .append("div")
      .attr("class", "tooltip")
      .style("opacity", 0);
    const simulation = d3
      .forceSimulation(data.nodes)
      .force(
        "link",
        d3
          .forceLink(data.links)
          .id((d) => d.id)
          .distance(100)
      )
      .force("charge", d3.forceManyBody().strength(-30))
      .force("center", d3.forceCenter(width / 2, height / 2));
    svg
      .append("defs")
      .append("marker")
      .attr("id", "arrow")
      .attr("viewBox", "0 -5 10 10")
      .attr("refX", 16)
      .attr("refY", 0)
      .attr("markerWidth", 10)
      .attr("markerHeight", 10)
      .attr("orient", "auto")
      .append("path")
      .attr("d", "M0,-5L10,0L0,5")
      .attr("class", "arrowHead");

    const label = svg
      .selectAll(".label")
      .data(data.nodes)
      .enter()
      .append("text")
      .attr("class", "label")
      .text((d) => d.label);
    const link = svg

      .attr("stroke", "black")
      .attr("stroke-opacity", 0.4)
      .selectAll("line")
      .data(data.links)
      .join("line")
      .attr("marker-end", "url(#arrow)"); // 添加箭头标记

    const node = svg
      .attr("stroke", "#69b3a2")
      .attr("stroke-width", 1.5)
      .selectAll("circle")
      .data(data.nodes)
      .join("circle")
      .attr("r", 10)
      .attr("fill", "#69b3a2")
      .on("mouseover", function (d, event) {
        console.log(event.id, d.srcElement.__data__.id);
        tooltip.transition().duration(200).style("opacity", 1);
        const [x, y] = d3.pointer(event);
      })
      .on("click", this.handleNodeClick)
      .call(
        d3
          .drag()
          .on("start", this.dragStarted)
          .on("drag", this.dragged)
          .on("end", this.dragEnded)
      );
    node
      .attr("class", "node-label")
      .attr("x", 12)
      .attr("y", 5)
      .append("title")
      .text((d) => d.id);
    this.simulation = simulation;
    simulation.on("tick", () => {
      link
        .attr("x1", (d) => d.source.x)
        .attr("y1", (d) => d.source.y)
        .attr("x2", (d) => d.target.x)
        .attr("y2", (d) => d.target.y);

      node.attr("cx", (d) => d.x).attr("cy", (d) => d.y);
      label.attr("x", (d) => d.x).attr("y", (d) => d.y - 10); // 调整标签的位置
    });
    function zoomed(event) {
      // 获取当前的缩放状态
      var transform = event.transform;
      svg.attr("transform", transform);
    }
  }

  dragStarted = (event, d) => {
    if (!event.active) this.simulation.alphaTarget(0.3).restart();
    d.fx = d.x;
    d.fy = d.y;
  };
  dragged = (event, d) => {
    d.fx = event.x;
    d.fy = event.y;

    // 更新节点和链接的位置
    const svg = d3.select(this.myRef.current);
    const link = svg.selectAll("line");
    const node = svg.selectAll("circle");
    const label = svg.selectAll(".label");

    link
      .attr("x1", (d) => d.source.x)
      .attr("y1", (d) => d.source.y)
      .attr("x2", (d) => d.target.x)
      .attr("y2", (d) => d.target.y);

    node.attr("cx", (d) => d.x).attr("cy", (d) => d.y);
    label.attr("x", (d) => d.x).attr("y", (d) => d.y - 10); // 调整标签的位置
  };
  dragEnded = (event, d) => {
    if (!event.active) this.simulation.alphaTarget(0);
    d.fx = null;
    d.fy = null;
    const svg = d3.select(this.myRef.current);
    const label = svg.selectAll(".label");
    label.attr("x", (d) => d.x).attr("y", (d) => d.y - 10); // 调整标签的位置
  };
  render() {
    return (
      <div>
        <svg ref={this.myRef} width={600} height={600}></svg>;
      </div>
    );
  }
}
